#ifndef __PLANNER_RANDOM_HPP__
#define __PLANNER_RANDOM_HPP__

#include "Planner.hpp"
#include <random>

/**
 * @brief 规划器-随机策略
 * @note 随机取货并送往随机泊位，船到随机泊位取货
 */
class PlannerRandom : public Planner
{
private:
    int frameID = -1; // 当前帧
    const Map *map = nullptr; // 地图
    std::vector<Berth> *berths = nullptr; // 泊位
    const std::vector<Goods *> *goods_list = nullptr; // 货物
    const std::vector<BoatDispatcher> *boatDispatchers = nullptr; // 机器人调度器
    const std::vector<RobotDispatcher> *robotDispatchers = nullptr; // 船调度器

public:
    /**
     * @brief 初始化
     * @param map 地图
     * @param berths 泊位列表
     * @param goods_list 货物列表
     * @param boatDispatchers 船调度器列表
     * @param robotDispatchers 机器人调度器列表
     * @note 初始化阶段调用一次，连接到可用的地图和泊位、货物列表等，由外部保证这些数据实时刷新
     */
    void init(const Map *map, std::vector<Berth> *berths, const std::vector<Goods *> *goods_list,
        const std::vector<BoatDispatcher> *boatDispatchers,
        const std::vector<RobotDispatcher> *robotDispatchers) override {
        this->map = map;
        this->berths = berths;
        this->goods_list = goods_list;
        this->boatDispatchers = boatDispatchers;
        this->robotDispatchers = robotDispatchers;
    }
    /**
     * @brief 刷新一帧
     * @param frameID 当前帧
     * @param newGoodsNum 新增货物数
     * @note  每帧运行一次（可能存在跳帧），新增货物数用于倒序遍历goods_list
     */
    void refresh(int frameID, int newGoodsNum) override {
        (void) newGoodsNum; // 不使用
        this->frameID = frameID;
    }
    /**
     * @brief 给指定机器人分配任务
     * @param robot 指定机器人
     * @return PlanForLand 分配的任务
     */
    PlanForLand allocatePlan(const Robot *robot) override {
        (void) robot; // 不使用
        for (auto it = (*goods_list).rbegin(); it != (*goods_list).rend(); ++it){
            if ((*it)->isAvailable(frameID)) {
                return PlanForLand((*it), random() % BERTH_NUM);
            }
        }
        return PlanForLand();
    }
    /**
     * @brief 给指定船分配任务
     * @param boat 指定船
     * @return PlanForSea 分配的任务
     */
    PlanForSea allocatePlan(const Boat *boat) override {
        int berthID = random() % BERTH_NUM;
        // 时间 = 当前帧 + 到达港口时间 + 该泊位把船装满所需时间
        int time = frameID + (*berths)[berthID].distance + boat->volume / (*berths)[berthID].velocity;
        return PlanForSea(berthID, time);
    }
};

#endif // __PLANNER_RANDOM_HPP__